package com.demo;

import java.io.Serializable;
import java.security.*;
import java.util.ArrayList;

public class Transaction implements Serializable {
    private static final long serialVersionUID = 1L;
    
    public String from; // 这里简化为交易双方的地址(公钥） // from-to结构过于简化，无法防止双花攻击
    public String to;
    public int amount; // 交易金额
    public byte[] signature; // 交易的签名

    public Transaction(String from, String to, int amount) throws Exception {
        this.from = from;
        this.to = to;
        this.amount = amount;
    }

    // 获取交易的哈希
    public String getTxHash(){
        return Utils.SHA256(from,to, String.valueOf(amount));
    }

    // 获取交易的签名
    public void sign(String sigKey) throws Exception {
        String msgToSign = this.toString();
        System.out.println("sigKey: "+sigKey);
        signature = ECCKeyGen.sign(sigKey, msgToSign);
    }

    // 验签名
    public boolean validate() throws Exception {
        if(this.from.equals("") || this.from.equals("出块交易无来源方")){ // 出块奖励的交易、创世交易
            return true;
        }
        String pubKeyStr = from;
        String message = this.toString();
        return ECCKeyGen.verify(pubKeyStr, message,signature);
    }

    @Override
    public String toString() {
        return "com.demo.Transaction{" +
                "from='" + from + '\'' +
                ", to='" + to + '\'' +
                ", amount=" + amount +
                '}';
    }

    @Override
    public Transaction clone() throws CloneNotSupportedException {
        try {
            Transaction cloned = new Transaction(this.from, this.to, this.amount);
            cloned.signature = this.signature != null ? this.signature.clone() : null;
            return cloned;
        } catch (Exception e) {
            throw new CloneNotSupportedException("克隆交易失败: " + e.getMessage());
        }
    }

    public String getFrom(){ // 发款方公钥
        return from;
    }
    public String getTo(){ // 收款方公钥
        return to;
    }

    // 检查交易是否是有效的UTXO
    public boolean isValidUTXO(Chain blockchain) {
        // 如果是创世交易或出块奖励交易，直接返回true
        if (this.from.equals("") || this.from.equals("出块交易无来源方")) {
            return true;
        }

        // 检查交易是否已经被花费
        for (Block block : blockchain.getChain()) {
            for (Transaction tx : block.transactions) {
                if (tx.from.equals(this.from) && tx.amount == this.amount) { // todo：无法真正防止双花攻击
                    return false; // 交易已被花费
                }
            }
        }
        return true;
    }

    // 检查交易金额是否足够
    public boolean hasSufficientFunds(Chain blockchain) {
        if (this.from.equals("") || this.from.equals("出块交易无来源方")) {
            return true;
        }

        int totalBalance = 0;
        for (Block block : blockchain.getChain()) {
            for (Transaction tx : block.transactions) {
                if (tx.to.equals(this.from) && tx.isValidUTXO(blockchain)) { // 此时区块链收录的交易中支付给此次交易发起方的总额（是否还有钱）
                    totalBalance += tx.amount;
                }
                if (tx.from.equals(this.from)) {
                    totalBalance -= tx.amount;
                }
            }
        }
        return totalBalance >= this.amount;
    }

    // 接收方验证交易
    public boolean validateAsReceiver(Chain blockchain) throws Exception {
        // 基本签名验证
        if (!validate()) {
            System.out.println("交易签名验证失败");
            return false;
        }

        // 检查是否是有效的UTXO
        if (!isValidUTXO(blockchain)) {
            System.out.println("交易已被花费");
            return false;
        }

        // 检查支付方余额是否足够
        if (!hasSufficientFunds(blockchain)) {
            System.out.println("支付方余额不足");
            return false;
        }

        return true;
    }
}
